home *** CD-ROM | disk | FTP | other *** search
/ Shareware Grab Bag / Shareware Grab Bag.iso / 015 / tsetup.arc / TSETUP.ASM next >
Encoding:
Assembly Source File  |  1987-07-04  |  27.6 KB  |  590 lines

  1.         name    tsetup
  2.         title    'TSETUP --- Toshiba Printer Setup Utility'
  3. ; TSETUP -- Memory resident utility to setup Toshiba P321/P341/P351 Printers
  4. ;
  5. ; Program is loaded once from prompt or from autoexec.bat file and stays
  6. ; resident in memory.  Once loaded utility menu can be called trigger key
  7. ; <ctrl><rt shift>.  When utility is called window opens in center of 
  8. ; screen displaying options.  The escape key is used to close the window
  9. ; and return to original program.
  10. ;
  11. ; Copyright (c) 1986, Caro Research Associates
  12. ; Portions of Copyright (c) 1986, Ziff-Davis Publishing Company
  13. ;
  14. ; May be freely modified and reproduced
  15. ; for non-commercial use.
  16. ;
  17. ; Caro Research Associates
  18. ; 202 S. 22nd Street
  19. ; Tampa, FL  33605
  20. ; 813/248-0852
  21. ;
  22. ;
  23. interrupts    segment at 0h                      ;interrupt table segment
  24.               org 9h*4
  25. keyboard_int  dw 2 dup (?)                       ;interrupt 9 vector
  26. interrupts    ends
  27. ;
  28. rom_bios_data segment at 40h                     ;ROM BIOS data area segment
  29.               org 60h
  30. ;
  31. cursor_mode   dw ?            ;starting and ending cursor scan lines
  32. rom_bios_data ends
  33. ;
  34. rom           segment at 0F000h                  ;ROM segment
  35.               org 0FFFEh
  36. ;
  37. machine_id    db ?                ;ID byte identifies machine as PCjr or other
  38. rom           ends
  39. ;
  40. code          segment para public 'code'         ;code segment
  41.               assume cs:code
  42.               org 100h
  43. ;
  44. begin:        jmp initialize                     ;goto initialization routine
  45. ;
  46. ;
  47. column_count  dw ?                               ;width of window in columns
  48. cursor_type   dw ?                               ;cursor scan line definition
  49. setup_status  db 0          ;indicates if printer window is already active
  50. display_mode  dw ?                               ;current crt display mode
  51. page_no       dw ?                               ;current displayed page
  52. attribute1    db 4Fh                             ;window attribute bytes
  53. attribute2    db 70h
  54. ;
  55. display_table db 2Dh,29h    ;display re-enable values for modes 2 and 3
  56. video         dw 0B800h,0B900h,0BA00h,0BB00h     ;starting addresses of video
  57.                                                  ;memory for CGA pages 0 - 3
  58. ;
  59. mono_video    dw 0B000h                          ;video segment address for
  60.                          ;monochrome adapter
  61. ;
  62. old_kb_int              label dword
  63. old_keyboard_int        dw 2 dup (?)             ;storage for old keyboard
  64.                          ;interrupt vector
  65. ;
  66. ;----------------------------------------------------------------------------
  67. ;Text of the Printer Setup Menu window.
  68. ;After initialization, text and attribute bytes are combined and stored
  69. ;in the WINDOW_TEXT area, and this area is used to store the contents of
  70. ;the screen that underlie the window when the window is called up.
  71. ;----------------------------------------------------------------------------
  72. ;
  73. window_buffer           label word
  74. ;                               00000000011111111112222222
  75. ;                               12345678901234567890123456
  76. buffer_text             db 201,26 dup (205),187
  77.                         db 186,'    Printer Setup Menu    ',186
  78.                         db 186,'  TOSHIBA P321/P341/P351  ',186
  79.                         db 204,26 dup (205),185
  80.                         db 186,' F1  Compressed Print Mode',186
  81.                         db 186,' F2  Elongated Print Mode ',186
  82.                         db 186,' F3  Shadow Print Mode    ',186
  83.                         db 186,' F4  Italics Print Mode   ',186
  84.                         db 186,' F5  Proportional Print   ',186
  85.                         db 186,' Unshifted:   Toggle ON   ',186
  86.                         db 186,' Shifted:     Toggle OFF  ',186
  87.                         db 204,26 dup (205),185
  88.                         db 186,' F6  Elite   SF6  Courier ',186
  89.                         db 186,' F7  HS 10   SF7  HS 12   ',186
  90.                         db 186,' F8  12 CPI  SF8  10 CPI  ',186
  91.                         db 204,26 dup (205),185
  92.                         db 186,' F9   Initialize Printer  ',186
  93.                         db 186,' F10  Formfeed  ESC  EXIT ',186
  94.                         db 200,205,'Caro Research Associates',205,188
  95.                         db 532 dup (?)
  96. ;
  97. ;Storage area for the combination of text and attribute bytes that
  98. ;form the window image.
  99. ;
  100. window_bytes  label byte
  101. window_text   dw 532 dup (?)
  102. ;
  103. ;Control code strings for all of the printer setup options.
  104. ;
  105. code_table:   db 27,42,48,27,91,7,255,13 dup (0)    ;compressed mode on
  106.               db 27,33,7,255,13 dup (0)                 ;elongated mode on
  107.               db 27,81,7,255,13 dup (0)                 ;shadow print on
  108.               db 27,18,27,81,7,255,13 dup (0)           ;italics on
  109.               db 27,36,7,255,13 dup (0)                 ;proportional on
  110.               db 27,42,49,7,255,13 dup (0)              ;elite font
  111.               db 27,69,49,50,27,42,48,7,255,13 dup (0)  ;high speed 10 pitch
  112.               db 27,69,49,50,7,255,13 dup (0)           ;10 cpi
  113.               db 27,26,73,12,7,255,13 dup (0)           ;initialize printer
  114.               db 12,7,255 dup (0)                       ;formfeed
  115. ;
  116.               db 27,93,7,255,13 dup (0)                ;compress off
  117.               db 27,34,7,255,13 dup (0)                 ;elongated mode off
  118.               db 27,82,7,255,13 dup (0)                 ;shadow print off
  119.               db 27,20,27,82,7,255,13 dup (0)           ;italics off
  120.               db 27,37,7,255,13 dup (0)                 ;proportional off
  121.               db 27,42,50,7,255,13 dup (0)              ;courier font
  122.               db 27,69,49,48,27,42,48,7,255,13 dup (0)  ;high speed 12 pitch
  123.               db 27,69,49,48,7,255,13 dup (0)           ;12 cpi
  124. ;
  125. ;---------------------------------------------------------------------------
  126. ;Execution comes here, to the main body of the program, when an interrupt 9
  127. ;is generated from the keyboard.  Registers are saved, then the keypress is
  128. ;checked and compared to the key combination that activates the menu window.
  129. ;---------------------------------------------------------------------------
  130. ;
  131. main          proc near
  132.               sti                                ;enable software interrupts
  133.               push ax                            ;save all registers
  134.               push bx
  135.               push cx
  136.               push dx
  137.               push si
  138.               push di
  139.               push ds
  140.               push es
  141.               push ax                ;save ax for call to old routine
  142.               in al,0A0h                         ;re-enable NMI on PCjr
  143.               pop ax                             ;restore ax
  144.               pushf          ;simulate interrupt call to old keyboard routine
  145.               call old_kb_int                    ;call old routine
  146.               mov ah,2                   ;check status of the shift keys
  147.               int 16h
  148.               and al,5                           ;Ctrl and Rt-Shift depressed?
  149.               cmp al,5
  150.               je do_program                      ;yes, then skip exit routine
  151. ;
  152. ;Exit routine is the common point of exit for all routines in the program.
  153. ;
  154. exit:         pop es
  155.               pop ds
  156.               pop di
  157.               pop si
  158.               pop dx
  159.               pop cx
  160.               pop bx
  161.               pop ax
  162.               iret
  163. ;
  164. ;Execution comes here when the proper key combination, Ctrl/Rt-Shift, is
  165. ;pressed.  First task is to check whether or not the window is already open.
  166. ;
  167. do_program:   push cs              ;set es and ds to the code segment
  168.               pop ds
  169.               push cs
  170.               pop es
  171.               cmp setup_status,0                 ;is the window already open?
  172.               jne exit                           ;yes, then ignore request
  173. ;
  174. ;----------------------------------------------------------------------------
  175. ;Check current video mode.  If it's mode 2, 3, or 7, then set the window
  176. ;status flag, store the mode number and page number, save the cursor type,
  177. ;and hide the cursor.  If any other display mode is active instead, ignore
  178. ;the request and exit.
  179. ;----------------------------------------------------------------------------
  180. ;
  181.               mov ah,15                          ;get page and mode numbers
  182.               int 10h                            ;al=mode, bh=page
  183.               cmp al,2                ;is crt now in an acceptable mode?
  184.               je prog0                           ;yes, then continue
  185.               cmp al,3
  186.               je prog0
  187.               cmp al,7
  188.               je prog0
  189.               jmp exit                           ;no, then ignore request
  190. prog0:        mov setup_status,1                 ;set status flag to indicate
  191.                                                  ;that window is active
  192.               mov ah,0                           ;save mode number
  193.               mov display_mode,ax
  194.               push bx
  195.               mov bl,bh               ;save page number for color displays
  196.               mov bh,0
  197.               mov page_no,bx
  198.               pop bx
  199.               mov ah,3                           ;get cursor type
  200.               int 10h
  201.               mov cursor_type,cx                 ;save it
  202.               mov ah,1                           ;hide the cursor until later
  203.               mov ch,20h
  204.               int 10h
  205. ;
  206. ;Preparatory routines are completed.  Now open the window by first saving the
  207. ;contents of video memory beneath the window and then writing the window text
  208. ;directly to memory.
  209. ;
  210.               mov bx,page_no             ;use bx as index into video segment
  211.                                          ;address table
  212.               cmp display_mode,7         ;manually adjust index for monochrome
  213.                                          ;adapter
  214.               jne prog1
  215.               mov bx,4
  216. prog1:        shl bx,1                           ;multiply bx by two since
  217.                                                  ;table is made up of words
  218.               mov ax,video[bx]                   ;read segment from table
  219.               mov ds,ax                          ;ds set to video memory
  220.               cmp display_mode,7                 ;skip disable if in mode 7
  221.               je prog2
  222.               call video_disable      ;turn display off for snow-free writing
  223. prog2:        lea di,window_buffer         ;set di to buffer area to save
  224.                                            ;screen contents
  225.               mov ch,28               ;define window dimensions and location
  226.               mov cl,19
  227.               mov dh,2
  228.               mov dl,26
  229.               call video2mem          ;then transfer screen contents to buffer
  230.               push ds                            ;set es to video memory
  231.               pop es
  232.               push cs                            ;reset ds to code segment
  233.               pop ds
  234.               lea si,window_text                 ;point si to window image
  235. prog3:        mov ch,28                          ;define window region
  236.               mov cl,19
  237.               mov dh,2
  238.               mov dl,26
  239.               call mem2video         ;and write the window to the display
  240.               cmp display_mode,7                 ;skip enable if in mode 7
  241.               je getkey
  242.               call video_enable                  ;re-enable the video display
  243. ;
  244. ;Window is now present on the screen, so wait for a keypress.
  245. ;
  246. getkey:      mov ah,0                           ;get a keypress
  247.               int 16h
  248.               cmp al,0                           ;is it an extended code?
  249.               je extended_code                   ;yes, go interpret it
  250.               cmp al,27                          ;is it the ESC key?
  251.               jne getkey1           ;no, then signal illegal keypress
  252. ;
  253. ;----------------------------------------------------------------------------
  254. ;Execution comes here when the ESC key is pressed.  The window is refilled
  255. ;with its original contents, the cursor is restored, and control is handed
  256. ;back to the application program.
  257. ;----------------------------------------------------------------------------
  258. ;
  259.               cmp display_mode,7                 ;skip disable if in mode 7
  260.               je prog4
  261.               call video_disable                 ;turn off the display
  262. prog4:        lea si,window_buffer               ;point si to the buffer area
  263.               mov ch,28                          ;define the window
  264.               mov cl,19
  265.               mov dh,2
  266.               mov dl,26
  267.               call mem2video     ;and write the buffer contents to the display
  268.               cmp display_mode,7                 ;skip enable if in mode 7
  269.               je prog5
  270.               call video_enable                  ;turn display back on
  271. prog5:        mov ah,1                           ;restore cursor
  272.               mov cx,cursor_type
  273.               int 10h
  274.               mov setup_status,0                 ;reset window status
  275.               jmp exit                           ;and exit
  276. ;
  277. ;Getkey1 routine handles an illegal keypress by beeping and returning
  278. ;for another.
  279. ;
  280. getkey1:      call beep              ;beep and return for another keypress
  281.               jmp getkey
  282. ;
  283. ;An extended code has been entered...check its validity and goto the
  284. ;appropriate routine.
  285. ;
  286. extended_code:
  287.               cmp ah,59                          ;less than F1?
  288.               jb getkey1                         ;yes, then don't accept it
  289.               cmp ah,91                          ;greater than Shft-F8?
  290.               ja getkey1                         ;yes, then don't accept it
  291.               cmp ah,68                          ;between F1 and F10?
  292.               jbe unshifted                      ;yes
  293.               cmp ah,84                          ;between Shft-F1 and Shft-F9?
  294.               jae shifted                        ;yes
  295.               jmp getkey1     ;if all tests failed, then keypress was illegal
  296. ;
  297. ;----------------------------------------------------------------------------
  298. ;If a legal function key was pressed, its scan code is translated here to the
  299. ;starting address of the string of bytes to be sent to the printer.  The
  300. ;string is then sent to LPT1: provided it's powered on and on-line.
  301. ;----------------------------------------------------------------------------
  302. ;
  303. shifted:      sub ah,15               ;adjustment for shifted function keys
  304. unshifted:    sub ah,59                ;adjustment for unshifted function keys
  305.               mov al,ah                          ;convert index to word in ax
  306.               xor ah,ah
  307.               mov cl,4                           ;multiply ax by 16
  308.               shl ax,cl
  309.               add ax,offset code_table     ;convert ax to full offset address
  310.               mov si,ax                          ;and transfer it to si
  311.               call lpt1stat                      ;check for printer ready
  312.               jc getkey1                         ;beep if printer not ready
  313.               mov bl,255               ;specify delimiter for call to LPRINTZ
  314.               call lprintz             ;send control code string to printer
  315.               jmp getkey                         ;return for another keypress
  316. ;
  317. main          endp                               ;end of main body of program
  318. ;
  319. ;---------------------------------------------------------------------------
  320. ;VIDEO_ENABLE and VIDEO_DISABLE routines manipulate bit 3 of port 3D8h,
  321. ;the CGA Mode Control Register, to temporarily turn the display on or off.
  322. ;Since these routines write directly to hardware, they have no effect on
  323. ;other video adapters.
  324. ;---------------------------------------------------------------------------
  325. ;
  326. video_disable proc near
  327.               mov dx,3DAh                        ;read CGA status port
  328. disable1:     in al,dx               ;wait for vertical retrace to occur
  329.               test al,8                          ;is bit 3 set?
  330.               je disable1                        ;no, wait until it is
  331.               mov dx,3D8h                        ;now disable the display
  332.               mov al,25h      ;by clearing bit 3 of the Mode Control Register
  333.               out dx,al
  334.               ret
  335. video_disable endp
  336. ;
  337. video_enable  proc near
  338.               mov dx,3D8h                        ;CGA Mode Control Register
  339.               mov bx,display_mode        ;get value to re-enable display
  340.               sub bx,2
  341.               mov al,display_table[bx]
  342.               out dx,al                          ;and send it to the port
  343.               ret
  344. video_enable  endp
  345. ;
  346. ;---------------------------------------------------------------------------
  347. ;VIDEO2MEM routine transfers the contents of a portion of video memory
  348. ;to a memory buffer for storage.
  349. ;Entry:       DS    - video segment
  350. ;             ES:DI - memory buffer
  351. ;             DH,DL - row and column of upper left corner of window
  352. ;             CH    - width of window in columns
  353. ;             CL    - number of lines in window
  354. ;---------------------------------------------------------------------------
  355. ;
  356. video2mem     proc near
  357.               mov al,ch                          ;store number of columns
  358.               mov ah,0
  359.               mov column_count,ax
  360.               mov ch,0                           ;cx = number of lines
  361.               push di                            ;save di
  362.               call video_offset        ;get cell address of first character
  363.               mov si,di                          ;put it in si
  364.               pop di                             ;restore di
  365. v2mem1:       push si                            ;save si for next line
  366.               push cx                            ;save line count
  367.               mov cx,column_count                ;set cx for call to WRITELN
  368.               call writeln                       ;transfer one line
  369.               pop cx                             ;restore saved registers
  370.               pop si
  371.               add si,160                         ;set si for next line address
  372.               loop v2mem1                ;loop until all lines are done
  373.               ret
  374. video2mem     endp
  375. ;
  376. ;---------------------------------------------------------------------------
  377. ;MEM2VIDEO writes a selected area of memory to the video display.
  378. ;Entry:       DS:SI - memory buffer
  379. ;             ES    - video segment
  380. ;             DH,DL - row and column of upper left corner of window
  381. ;             CH    - width of window in columns
  382. ;             CL    - number of lines in window
  383. ;---------------------------------------------------------------------------
  384. ;
  385. mem2video     proc near
  386.               mov al,ch                          ;save number of columns
  387.               mov ah,0
  388.               mov column_count,ax
  389.               mov ch,0                           ;cx = number of lines
  390.               call video_offset                  ;get offset into video memory
  391. mem2v1:       push di                            ;save video starting address
  392.               push cx                            ;save line count
  393.               mov cx,column_count                ;set cx for call to WRITELN
  394.               call writeln                       ;transfer one line
  395.               pop cx                             ;restore registers
  396.               pop di
  397.               add di,160                         ;set di for next display line
  398.               loop mem2v1                        ;loop until done
  399.               ret
  400. mem2video     endp
  401. ;
  402. ;---------------------------------------------------------------------------
  403. ;VIDEO_OFFSET calculates the offset into video memory of a character cell.
  404. ;Entry:       DH,DL - row and column of cell (0-24,0-79)
  405. ;Exit:        DI    - offset address
  406. ;---------------------------------------------------------------------------
  407. ;
  408. video_offset  proc near
  409.               mov al,160
  410.               mul dh                             ;row * 160
  411.               shl dl,1                           ;column * 2
  412.               mov dh,0                           ;byte to word
  413.               add ax,dx                          ;(row *160)+(column*2)
  414.               mov di,ax                          ;set offset in di
  415.               ret
  416. video_offset  endp
  417. ;
  418. ;---------------------------------------------------------------------------
  419. ;WRITELN subroutine copies a string of words from one memory location to
  420. ;another.  The CGA status port is not checked for vertical retrace status
  421. ;before transfer.
  422. ;Entry:       DS:SI - source
  423. ;             ES:DI - destination
  424. ;             CX    - number of words
  425. ;---------------------------------------------------------------------------
  426. ;
  427. writeln       proc near
  428.               cld                     ;clear for string instructions
  429. write1:       movsw                              ;move one word
  430.               loop write1                        ;loop until done
  431.               ret
  432. writeln       endp
  433. ;
  434. ;---------------------------------------------------------------------------
  435. ;LPRINTZ routine sends a string of bytes delimited by a user-specified byte to
  436. ;LPT1: thru INT 17h.
  437. ;Entry:       DS:SI - string address
  438. ;             BL    - delimiter (0-255)
  439. ;---------------------------------------------------------------------------
  440. ;
  441. lprintz       proc near
  442.               cld                                ;for 8088 string instructions
  443. lprintz1:     lodsb                              ;get one byte
  444.               cmp al,bl                          ;is it the delimiter?
  445.               je lprintz2                        ;yes, then exit
  446.               mov dx,0                           ;printer no. 0 (LPT1:)
  447.               mov ah,0
  448.               int 17h                            ;send byte to printer
  449.               jmp lprintz1                       ;return for next byte
  450. lprintz2:     ret
  451. lprintz       endp
  452. ;
  453. ;---------------------------------------------------------------------------
  454. ;LPT1STAT checks the current status of printer LPT1:.  If it's either
  455. ;powered off or off-line, then an error condition is signalled upon return
  456. ;thru the carry flag.
  457. ;Exit:        Carry clear - no error
  458. ;             Carry set   - error
  459. ;---------------------------------------------------------------------------
  460. ;
  461. lpt1stat      proc near
  462.               mov dx,0                  ;printer no. 0
  463.               mov ah,2               ;use ROM BIOS 'get status' function
  464.               int 17h
  465.               test ah,8                 ;test bit 3, I/O error indicator
  466.               je stat1                  ;if clear, then no error
  467.               stc                       ;raise error flag
  468.               ret
  469. stat1:        clc                       ;clear error flag
  470.               ret
  471. lpt1stat      endp
  472. ;
  473. ;---------------------------------------------------------------------------
  474. ;BEEP uses the 8253 timer chip to emit a short beep thru the PC's speaker.
  475. ;---------------------------------------------------------------------------
  476. ;
  477. beep          proc near
  478.               mov al,182             ;notify 8253 that frequency data is coming
  479.               out 67,al
  480.               mov al,0                           ;send frequency (776.8 Hz)
  481.               out 66,al
  482.               mov al,6
  483.               out 66,al
  484.               in al,97                           ;activate speaker
  485.               or al,3
  486.               out 97,al
  487.               mov cx,6000h                 ;time delay for sound duration
  488. beep1:        loop beep1
  489.               in al,97                           ;deactivate speaker
  490.               and al,252
  491.               out 97,al
  492.               ret
  493. beep          endp
  494. ;
  495. ;---------------------------------------------------------------------------
  496. ;MEM2MEM subroutine transfers a non-overlapping block of memory one byte
  497. ;at a time.
  498. ;Entry:       DS:SI - source
  499. ;             ES:DI - destination
  500. ;             CX    - number of bytes
  501. ;---------------------------------------------------------------------------
  502. ;
  503. mem2mem       proc near
  504.               cld
  505. mem1:         movsb                              ;transfer one byte
  506.               loop mem1                          ;and loop until done
  507.               ret
  508. mem2mem       endp
  509. ;
  510. ;---------------------------------------------------------------------------
  511. ;Initialization routine sets up the window image in the WINDOW_TEXT area,
  512. ;resets the CURSOR_MODE word if this is a PCjr, and saves and replaces the
  513. ;old keyboard interrupt vector.
  514. ;---------------------------------------------------------------------------
  515. ;
  516. initialize    proc near
  517. ;
  518. ;Initialize the window text area by combining the text data with the attribute
  519. ;bytes and placing the conglomeration in the WINDOW_TEXT area.
  520. ;
  521.               assume ds:code,es:code
  522.               mov ah,15                          ;check the current video mode
  523.               int 10h
  524.               cmp al,7              ;if it's mode 7, then replace the attribute
  525.               jne init0          ;bytes with ones appropriate for mono adapter
  526.               mov attribute1,70h
  527.               mov attribute2,07h
  528. init0:        cld              ;now combine the text and attribute bytes
  529.               lea si,buffer_text                 ;point si to table of text
  530.               lea di,window_bytes                ;and di to storage area
  531.               mov cx,112           ;create first four lines by combining
  532.               mov al,attribute1          ;text with attribute1 (112 words)
  533. init1:        movsb                              ;text byte
  534.               stosb                              ;attribute byte
  535.               loop init1                 ;loop until all 112 words are done
  536.               mov cx,11                          ;now do the next 11 lines
  537. init2:        push cx              ;first attribute in each line is attribute1
  538.               movsb
  539.               stosb
  540.               mov cx,26            ;next 26 attributes are attribute2
  541.               mov al,attribute2
  542. init3:        movsb
  543.               stosb
  544.               loop init3
  545.               movsb
  546.               mov al,attribute1     ;and the last in each line is attribute1
  547.               stosb
  548.               pop cx
  549.               loop init2            ;loop until all 11 lines are done
  550.               mov cx,112            ;create the last four lines just like
  551. init4:        movsb                 ;the first four
  552.               stosb
  553.               loop init4
  554. ;
  555. ;Check the machine ID byte in ROM and if this is a PCjr, then reset the
  556. ;cursor and correct the CURSOR_MODE word at 0040:0060.
  557. ;
  558.               mov ax,rom                         ;set ds to rom
  559.               mov ds,ax
  560.               assume ds:rom
  561.               cmp machine_id,0FDh                ;is this a PCjr?
  562.               jne init5                          ;no, then skip this routine
  563.               mov ax,rom_bios_data               ;set ds to ROM BIOS data area
  564.               mov ds,ax
  565.               assume ds:rom_bios_data
  566.               mov cursor_mode,0607h          ;reset the cursor mode indicator
  567.               mov ah,1                       ;then physically reset the cursor
  568.               mov cx,0607h
  569.               int 10h
  570. ;
  571. ;Now save the old keyboard interrupt vector and replace it with the new one.
  572. ;
  573. init5:        mov ax,interrupts          ;set ds to the interrupt vector area
  574.               mov ds,ax
  575.               assume ds:interrupts
  576.               mov ax,keyboard_int                ;save old vector
  577.               mov old_keyboard_int,ax
  578.               mov ax,keyboard_int[2]
  579.               mov old_keyboard_int[2],ax
  580.               cli                        ;disable all interrupts but NMI
  581.               mov keyboard_int,offset main       ;and install new vector
  582.               mov keyboard_int[2],cs
  583.               sti                                ;re-enable interrupts
  584.               mov dx,offset initialize   ;point dx to end of resident section
  585.               int 27h                            ;terminate-but-stay-resident
  586. initialize    endp
  587. ;
  588. code          ends
  589.               end begin
  590.